package com.pair.micro.common.exception;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.alibaba.fastjson.JSON;
import com.pair.micro.common.constant.MicroBusinessError;
import com.pair.micro.common.constant.MicroSystemError;
import com.pair.micro.common.response.MicroResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.nio.file.AccessDeniedException;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * 全局异常拦截
 *
 *
 *
 *
 * @author xubz
 * @since 2023
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(Throwable.class)
  public MicroResult handleException(Throwable e) {
    log.error(ExceptionUtil.getMessage(e), e);
    return buildSys(MicroSystemError.SYS_00002);
  }

  @ExceptionHandler(Exception.class)
  public MicroResult handleException(Exception e) {
    log.error(ExceptionUtil.getMessage(e), e);
    return buildSys(MicroSystemError.SYS_00002);
  }

  @ExceptionHandler(AccessDeniedException.class)
  public MicroResult handleAccessDeniedException(AccessDeniedException e) {
    log.error(ExceptionUtil.getMessage(e), e);
    return buildSys(MicroSystemError.SYS_00081);
  }

  @ExceptionHandler(MicroBadRequestException.class)
  public MicroResult handleMicroBadRequestException(MicroBadRequestException e) {
    log.error(ExceptionUtil.getMessage(e), e);
    return buildSys(e.getMicroSystemError());
  }

  @ExceptionHandler(MicroSystemException.class)
  public MicroResult handleMicroSystemException(MicroSystemException e) {
    log.error(ExceptionUtil.getMessage(e), e);
    return buildSys(e.getMicroSystemError(), e.getMessage());
  }

  @ExceptionHandler(MicroUpgradeException.class)
  public MicroResult handleMicroUpgradeException(MicroUpgradeException e) {
    log.error(ExceptionUtil.getMessage(e), e);
    return buildSys(e.getMicroSystemError());
  }

  @ExceptionHandler(MicroSecurityException.class)
  public MicroResult handleMicroSecurityException(MicroSecurityException e) {
    log.error(ExceptionUtil.getMessage(e), e);
    return buildBis(e.getMicroBusinessError());
  }

  @ExceptionHandler(MicroArgsNotValidException.class)
  public MicroResult handleMicroArgsNotValidException(MicroArgsNotValidException e) {
    log.error(ExceptionUtil.getMessage(e), e);
    return buildBis(e.getMicroBusinessError(), e.getMessage());
  }

  @ExceptionHandler(MicroBusinessException.class)
  public MicroResult handleMicroBusinessException(MicroBusinessException e) {
    log.error(ExceptionUtil.getMessage(e), e);
    return buildBis(e.getMicroBusinessError(), e.getMessage());
  }




  @ExceptionHandler(BindException.class)
  public MicroResult handleBindException(BindException e) {
    log.error(ExceptionUtil.getMessage(e), e);
    String[] str = e.getBindingResult().getAllErrors().get(0).getCodes()[1].split("\\.");
    StringBuffer msg = new StringBuffer(str[1] + ":");
    msg.append(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    return buildBis(MicroBusinessError.BIS_10007, msg.toString());
  }

  @ExceptionHandler(MethodArgumentNotValidException.class)
  public MicroResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
    log.error(ExceptionUtil.getMessage(e), e);
    String[] str = e.getBindingResult().getAllErrors().get(0).getCodes()[1].split("\\.");
    StringBuffer msg = new StringBuffer(str[1] + ":");
    msg.append(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    return buildBis(MicroBusinessError.BIS_10007, msg.toString());
  }

  @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
  public MicroResult handleHttpRequestMethodNotSupportedException(
      HttpRequestMethodNotSupportedException e) {

    log.info(e.getMessage());
    log.info(JSON.toJSONString(e.getSupportedMethods()));
    //  Request method 'GET' not supported
    return buildSys(
            MicroSystemError.SYS_00083,
        "接口仅支持" + Arrays.stream(e.getSupportedMethods()).collect(Collectors.joining("、")) + "方式请求");
  }

  private MicroResult buildBis(MicroBusinessError microBusinessError) {
    return MicroResult.BisError(microBusinessError);
  }

  private MicroResult buildBis(MicroBusinessError microBusinessError, String errorMsg) {
    return MicroResult.BisError(microBusinessError, errorMsg);
  }

  private MicroResult buildSys(MicroSystemError MicroSystemError) {
    return MicroResult.SysError(MicroSystemError);
  }

  private MicroResult buildSys(MicroSystemError microSystemError, String errorMsg) {
    return MicroResult.SysError(microSystemError);
  }
}
